package cn.lg.soar.mvc.filter;

import cn.lg.soar.common.util.data.DataUtil;
import cn.lg.soar.mvc.model.RefererFilterProperties;
import cn.lg.soar.mvc.model.RefererFilterRule;
import jakarta.servlet.FilterRegistration;
import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.servlet.ServletContextInitializer;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;

import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author luguoxiang
 * @date 2022/9/5
 * 开源项目：https://gitee.com/lgx1992/lg-soar 求star！请给我star！请帮我点个star！
 */
public class RefererFilterRegistrar  extends SpringBootServletInitializer implements ServletContextInitializer {

    @Autowired
    private RefererFilterProperties props;

    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        // 白名单
        List<RefererFilterRule> whitelist = props.getWhitelist();
        if (DataUtil.isValuable(whitelist)) {
            int index = 0;
            // 循环增加拦截器
            for (RefererFilterRule rule : whitelist) {
                String[] paths = resolveUrlPatterns(rule.getPaths());
                Set<String> referers = resolveReferers(rule.getReferers());
                if (DataUtil.isEmpty(paths) || DataUtil.isEmpty(referers)) {
                    throw new RuntimeException("referer-whitelist configuration error：Must include the “path-patterns” and “referers”");
                }
                RefererWhitelistFilter filter = new RefererWhitelistFilter(referers, rule.isNullable());
                // 注册过滤器
                FilterRegistration.Dynamic dynamic = servletContext.addFilter("referer-whitelist-filter-" + index++, filter);
                dynamic.addMappingForUrlPatterns(null, false, paths); // 设置过滤所有请求
            }
        }
        // 黑名单
        List<RefererFilterRule> blacklist = props.getBlacklist();
        if (DataUtil.isValuable(blacklist)) {
            int index = 0;
            // 循环增加拦截器
            for (RefererFilterRule rule : blacklist) {
                String[] paths = resolveUrlPatterns(rule.getPaths());
                Set<String> referers = resolveReferers(rule.getReferers());
                if (DataUtil.isEmpty(paths) || DataUtil.isEmpty(referers)) {
                    throw new RuntimeException("referer-blacklist configuration error：Must include the “path-patterns” and “referers”");
                }
                RefererBlacklistFilter filter = new RefererBlacklistFilter(referers, rule.isNullable());
                // 注册过滤器
                FilterRegistration.Dynamic dynamic = servletContext.addFilter("referer-blacklist-filter-" + index++, filter);
                dynamic.addMappingForUrlPatterns(null, false, paths); // 设置过滤所有请求
            }
        }
    }

    private Set<String> resolveReferers(Set<String> referers) {
        if (referers == null) {
            return null;
        }
        return referers.stream()
                .map(String::trim)
                .filter(s -> !s.isEmpty())
                .collect(Collectors.toSet());
    }

    private String[] resolveUrlPatterns(Set<String> paths) {
        if (paths == null) {
            return null;
        }
        return paths.stream()
                .map(String::trim)
                .filter(s -> !s.isEmpty())
                .toArray(String[]::new);
    }
}